package net.csdn.business.common.oauth2.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.csdn.business.common.domain.request.oauth.*;
import net.csdn.business.common.enums.ResultCodeEnum;
import net.csdn.business.common.exception.BusinessException;
import net.csdn.business.common.oauth2.mapper.OauthAccessTokenMapper;
import net.csdn.business.common.oauth2.model.entity.OauthAccessToken;
import net.csdn.business.common.oauth2.model.entity.StatClientAuth;
import net.csdn.business.common.domain.vo.oauth.OauthAccessTokenVO;
import net.csdn.business.common.domain.vo.oauth.OauthClientInfoVo;
import net.csdn.business.common.oauth2.service.*;
import net.csdn.business.common.service.SnowflakeService;
import net.csdn.business.common.service.SuperServiceImpl;
import net.csdn.business.common.utils.UserInfoParser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * accessToken信息Service业务层处理
 *
 * @author zhangyl
 * @date 2022-11-08
 */
@Service
public class OauthAccessTokenServiceImpl extends SuperServiceImpl<OauthAccessTokenMapper, OauthAccessToken> implements IOauthAccessTokenService {

    @Autowired
    private SnowflakeService snowflakeService;

    @Autowired
    private IStatClientAuthService statClientAuthService;

    @Autowired
    private IOauthAuthLogService oauthAuthLogService;


    /**
     * 分页查询accessToken信息列表
     *
     * @param query accessToken信息
     * @return accessToken信息
     */
    @Override
    public IPage<OauthAccessTokenVO> findPageList(OauthAccessTokenQuery query) {
        // 获得Page对象
        Page<OauthAccessTokenVO> page = query.getPage();
        List<OauthAccessTokenVO> pageList = baseMapper.findPageList(page, query);
        page.setRecords(pageList);
        return page;
    }

    /**
     * 根据id查询accessToken信息
     *
     * @param tokenId accessToken信息的tokenId
     * @return accessToken信息
     */
    @Override
    public OauthAccessTokenVO selectByTokenId(String tokenId) {
        OauthAccessTokenVO result = null;
        LambdaQueryWrapper<OauthAccessToken> queryWrapper = new QueryWrapper<OauthAccessToken>().lambda();
        queryWrapper.eq(OauthAccessToken::getTokenId, tokenId);
        OauthAccessToken oauthAccessToken = baseMapper.selectOne(queryWrapper);
        if (oauthAccessToken != null) {
            result = new OauthAccessTokenVO();
            BeanUtils.copyProperties(oauthAccessToken, result);
        }
        return result;
    }

    /**
     * 根据authentId查询accessToken信息详细信息
     *
     * @param authentId accessToken信息的tokenId
     * @return accessToken信息
     */
    @Override
    public OauthAccessTokenVO selectByAuthentId(String authentId) {
        OauthAccessTokenVO result = null;
        LambdaQueryWrapper<OauthAccessToken> queryWrapper = new QueryWrapper<OauthAccessToken>().lambda();
        queryWrapper.eq(OauthAccessToken::getAuthenticationId, authentId);
        OauthAccessToken oauthAccessToken = baseMapper.selectOne(queryWrapper);
        if (oauthAccessToken != null) {
            result = new OauthAccessTokenVO();
            BeanUtils.copyProperties(oauthAccessToken, result);
        }
        return result;
    }

    /**
     * 查询accessToken信息列表
     *
     * @param query accessToken信息
     * @return accessToken信息
     */
    @Override
    public List<OauthAccessTokenVO> selectOauthAccessTokenList(OauthAccessTokenQuery query) {
        return baseMapper.selectOauthAccessTokenList(query);
    }

    /**
     * 新增accessToken信息
     *
     * @param newOauthAccessTokenDTO accessToken信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer insertOauthAccessToken(NewOauthAccessTokenDTO newOauthAccessTokenDTO) {
        OauthAccessToken oauthAccessToken = new OauthAccessToken();
        BeanUtils.copyProperties(newOauthAccessTokenDTO, oauthAccessToken);
        oauthAccessToken.setObjectId(snowflakeService.nextNo());
        oauthAccessToken.setCreatedDate(new Date());
        return baseMapper.insert(oauthAccessToken);
    }

    /**
     * 修改accessToken信息
     *
     * @param updateOauthAccessTokenDTO accessToken信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateOauthAccessToken(UpdateOauthAccessTokenDTO updateOauthAccessTokenDTO) {
        String id = updateOauthAccessTokenDTO.getObjectId();
        LambdaUpdateWrapper<OauthAccessToken> updateWrapper = new UpdateWrapper<OauthAccessToken>().lambda();
        updateWrapper.eq(OauthAccessToken::getObjectId, id);
        OauthAccessToken oauthAccessToken = new OauthAccessToken();
        ;
        BeanUtils.copyProperties(updateOauthAccessTokenDTO, oauthAccessToken);
        oauthAccessToken.setLastModifiedBy(UserInfoParser.getUserId());
        oauthAccessToken.setLastModifiedDate(new Date());
        return baseMapper.update(oauthAccessToken, updateWrapper);
    }

    /**
     * 删除accessToken信息信息
     *
     * @param id accessToken信息主键
     * @return 结果
     */
    @Override
    public OauthAccessToken getAccessTokenById(String id) {
        LambdaQueryWrapper<OauthAccessToken> queryWrapper = new QueryWrapper<OauthAccessToken>().lambda();
        queryWrapper.eq(OauthAccessToken::getObjectId, id);
        OauthAccessToken oauthAccessToken = baseMapper.selectOne(queryWrapper);
        if (oauthAccessToken == null) {
            throw new BusinessException(ResultCodeEnum.OAUTH_ACESS_TOKEN_ID_ERROR);
        }
        return oauthAccessToken;
    }


    /**
     * 删除accessToken信息信息
     *
     * @param  clientId clientId：客户端id; currUserId:当前操作用户id
     * @return 结果
     */
    @Override
    public List<OauthAccessToken> getAccessTokenByClientId(String clientId) {
        LambdaQueryWrapper<OauthAccessToken> queryWrapper = new QueryWrapper<OauthAccessToken>().lambda();
        queryWrapper.eq(OauthAccessToken::getClientId, clientId);
        // 删除accessToken
        List<OauthAccessToken> oauthAccessTokens = baseMapper.selectList(queryWrapper);
        return oauthAccessTokens;
    }

    /**
     * 删除accessToken信息信息
     *
     * @param tokenId accessToken信息主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer deleteByTokenId(String tokenId) {
        LambdaQueryWrapper<OauthAccessToken> queryWrapper = new QueryWrapper<OauthAccessToken>().lambda();
        queryWrapper.eq(OauthAccessToken::getTokenId, tokenId);
        return baseMapper.delete(queryWrapper);
    }

    /**
     * 删除accessToken信息信息
     *
     * @param refreshTokenId RefreshToken信息主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer deleteByRefreshTokenId(String refreshTokenId) {
        LambdaQueryWrapper<OauthAccessToken> queryWrapper = new QueryWrapper<OauthAccessToken>().lambda();
        queryWrapper.eq(OauthAccessToken::getRefreshToken, refreshTokenId);
        return baseMapper.delete(queryWrapper);
    }

    @Override
    public List<OauthAccessTokenVO> selectByClientIdAndUserName(String clientId, String userName) {
        List<OauthAccessTokenVO> result = null;
        LambdaQueryWrapper<OauthAccessToken> queryWrapper = new QueryWrapper<OauthAccessToken>().lambda();
        queryWrapper.eq(OauthAccessToken::getClientId, clientId);
        if (StringUtils.isNoneBlank(userName)) {
            queryWrapper.eq(OauthAccessToken::getUserName, userName);
        }
        List<OauthAccessToken> oauthAccessTokenlist = baseMapper.selectList(queryWrapper);
        if (oauthAccessTokenlist != null && oauthAccessTokenlist.size() > 0) {
            result = new ArrayList<>();
            for (OauthAccessToken oauthAccessToken : oauthAccessTokenlist) {
                OauthAccessTokenVO oauthAccessTokenVO = new OauthAccessTokenVO();
                BeanUtils.copyProperties(oauthAccessToken, oauthAccessTokenVO);
                result.add(oauthAccessTokenVO);
            }
        }
        return result;
    }


    @Override
    @Async
    public void statClientAuth(StatClientAuthQuery query) {
        // 查询授权日志明细，判断此用户今日是否已经授权过了
        String clentId = query.getClientId();
        String userName = query.getUserName();
        String statDate = query.getStatDate();
        Date authDate = DateUtil.parseDate(statDate);
        OauthAuthLogQuery authLogQuery = new OauthAuthLogQuery();
        authLogQuery.setClientId(clentId);
        authLogQuery.setUserName(userName);
        authLogQuery.setAuthDate(statDate);
        // 如果当天此用户还没授权过，则计入汇总表的数量里
        Integer count = oauthAuthLogService.selectOauthAuthLogCount(authLogQuery);
        if (count == 0) {
            StatClientAuth statClientAuth1 = statClientAuthService.selectStatClientAuth(query);
            if (statClientAuth1 != null) {
                statClientAuthService.updateStatClientAuth(query);
            } else {
                StatClientAuth statClientAuth = new StatClientAuth();
                statClientAuth.setObjectId(snowflakeService.nextNo());
                statClientAuth.setClientId(clentId);
                statClientAuth.setStatDate(authDate);
                statClientAuth.setAuthNums(1L);
                statClientAuthService.insertStatClientAuth(statClientAuth);
            }
        }
        // 插入授权日志
        NewOauthAuthLogDTO oauthAuthLog = new NewOauthAuthLogDTO();
        oauthAuthLog.setAuthDate(authDate);
        oauthAuthLog.setClientId(clentId);
        oauthAuthLog.setUserName(userName);
        oauthAuthLogService.insertOauthAuthLog(oauthAuthLog);
    }


    /**
     * 根据clientId查询已授权用户数量
     *
     * @param clientId oauth应用的clientId
     * @return oauth应用管理
     */
    @Override
    public Integer findAuthUserNum(String clientId) {
        return baseMapper.findAuthUserNum(clientId);
    }
}